
cmspad.apply(cmspad.console, {
	nls:{
		REQUIRE_PROFILE_LABEL: '<b>ERROR:</b> Please specify a label for your profile statement',
		CLICK_TO_FILTRATE: 'click to filter by message type',
		VISIBLE_ON_LOAD: 'Visible on page load',
		SMALL: 'Small',
		LARGE: 'Large',
		CLEAR: 'Clear',
		CLOSE: 'Close',
		LOADING: 'Loading console stylesheet files...'
	},
	toggle: function() { ( this.isVisible() ) ? this.hide() : this.show(); },
	debug: function( msg ) { this.addMessage( 'debug', msg ); },
	warn: function( msg ) { this.addMessage( 'warn', msg ); },
	info: function( msg ) { this.addMessage( 'info', msg ); },
	error: function( msg ) {
		// 当出现错误时，只要允许调试模式，就弹出调试控制台，便于Bug跟踪。
		if(!this.isVisible()){
			this.show();
		}
		this.addMessage( 'error', msg );
	},
	profile: function( label ) {
		var currentTime = new Date();
		if ( label == undefined || label == '' ) {
			this.addMessage( 'error', cmspad.console.nls.REQUIRE_PROFILE_LABEL );
		}
		else if ( this.profiler[ label ] ) {
			this.addMessage( 'profile', [ label, ': ', currentTime - this.profiler[ label ],	'ms' ].join( '' ) );
			delete this.profiler[ label ];
		}else {
			this.profiler[ label ] = currentTime;
			this.addMessage( 'profile', label );
		}
		return currentTime;
	},
	clear: function() { //clear list output
		this.outputList.innerHTML = '';
	},
	isVisible: function() { //determine the visibility
		return this.cconsole != null && this.cconsole.style.display == 'block';
	},
	hide: function() { 
		if(this.cconsole){
			this.cconsole.style.display = 'none';
		}
	},
	show: function() {
		var body = document.getElementsByTagName( 'BODY' )[ 0 ];
		if (this.cconsole) {
			body.removeChild(this.cconsole);
			body.appendChild(this.cconsole);
			this.cconsole.style.display = 'block';
		}
	},
	resize: function( size ) {
		if ( size === undefined || size === null ) {
			size = ( this.state && this.state.size == null ) ? 0 : ( this.state.size + 1 ) % 2;
		}
		this.classes[ 1 ] = ( size === 0 ) ? 'ccSmall' : 'ccLarge';
		var span = document.getElementById( this.IDs.size );
		span.title = ( size === 1 ) ? cmspad.console.nls.SMALL : cmspad.console.nls.LARGE;
		span.className = ( size === 1 ) ? 'small' : 'large';	  
		this.state.size = size;
		this._setState();
		this._scrollToBottom();
	},
	move: function( position ) {
		if ( position === undefined || position == null ) {
			position = ( this.state && this.state.pos === null ) ? 1 : ( this.state.pos + 1 ) % 4; //set to initial position ('topRight') or move to next position
		}
		switch ( position ) {
			case 0: this.classes[ 0 ] = 'ccTopLeft'; break;
			case 1: this.classes[ 0 ] = 'ccTopRight'; break;
			case 2: this.classes[ 0 ] = 'ccBottomLeft'; break;
			case 3: this.classes[ 0 ] = 'ccBottomRight'; break;
		}
		this.state.pos = position;
		this._setState();
	},
	cconsole:null,
	outputList:null,
	cache: [],
	state: { pos:null, size:null, load:null },
	classes: {},
	profiler: {},
	IDs: {
		cmspad_console: 'cmspad_console',
		checkbox: 'ccVis',
		filters: 'ccFilters',
		controls: 'ccControls',
		size: 'ccSize'
	},
	messageTypes: {
		debug: true,
		info: true,
		warn: true,
		error: true,
		profile: true
	},
	_generateMarkup: function() { //build markup
		var spans = [];
		for ( type in this.messageTypes ) {
			spans.push( [ '<span class="', type, '" type="', type, '"></span>'].join( '' ) );
		}
		var newNode = document.createElement( 'DIV' );
		newNode.id = this.IDs.cmspad_console;
		newNode.style.display = 'none';
		newNode.innerHTML = [
			'<div class="header">',
			'<div class="left">',
				'<div id="', this.IDs.filters, '" class="filters" title="' + cmspad.console.nls.CLICK_TO_FILTRATE + '">', spans.join( '' ), '</div>',
			'</div>',
			'<div class="right">',
				'<div id="', this.IDs.controls, '" class="controls">',
				'<span id="', this.IDs.size ,'" title="Resize" op="resize"></span>',
				'<span class="clear" title="' + cmspad.console.nls.CLEAR + '" op="clear"></span>',
				'<span class="close" title="' + cmspad.console.nls.CLOSE + '" op="close"></span>',
				'</div>',
			'</div>',
			'</div>',
			'<div class="main">',
			'<div class="left"></div><div class="mainBody">',
				'<ol>', this.cache.join( '' ), '</ol>',
			'</div><div class="right"></div>',
			'</div>',
			'<div class="footer">',
			'<div class="left"><label for="', this.IDs.checkbox, '"><input type="checkbox" id="', this.IDs.checkbox, '" />' + cmspad.console.nls.VISIBLE_ON_LOAD + '</label></div>',
			'<div class="right"></div>',
			'</div>'
		].join( '' );
		return newNode;
	},
	_backgroundImage: function() { //(IE6 only) change <BODY> tag's background to resolve {position:fixed} support
		var bodyTag = document.getElementsByTagName( 'BODY' )[ 0 ];
		if ( bodyTag.currentStyle) {
			if (bodyTag.currentStyle.backgroundImage == 'none' ) {
				bodyTag.style.backgroundImage = 'url(about:blank)';
			}
			if (bodyTag.currentStyle.backgroundAttachment == 'scroll' ) {
				bodyTag.style.backgroundAttachment = 'fixed';
			}
		}
	},
	addMessage: function( type, content ) { //adds a message to the output list
		content = ( content.constructor == Array ) ? content.join( '' ) : content;
		if ( this.outputList ) {
			var newMsg = document.createElement( 'LI' );
			newMsg.className = type;
			newMsg.innerHTML = [ '<span class="icon"></span>', content ].join( '' );
			this.outputList.appendChild( newMsg );
			this._scrollToBottom();
		} else {
			this.cache.push( [ '<li class="', type, '"><span class="icon"></span>', cmspad.encodeHtmlEntity(content), '</li>' ].join( '' ) );
		}
	},
	_clickControl: function( evt ) {
		if ( !evt ) evt = window.event;
		var el = ( evt.target ) ? evt.target : evt.srcElement;
		if ( el.tagName == 'SPAN' ) {
			switch ( el.getAttributeNode( 'op' ).nodeValue ) {
			case 'resize': cmspad.console.resize(); break;
			case 'clear':  cmspad.console.clear();  break;
			case 'close':  cmspad.console.hide();   break;
			}
		}
	},
	_clickFilter: function( evt ) { //show/hide a specific message type
		if ( !evt ) evt = window.event;
		var span = ( evt.target ) ? evt.target : evt.srcElement;
		if ( span && span.tagName == 'SPAN' ) {
			var type = span.getAttributeNode( 'type' ).nodeValue;
			if ( evt.altKey ) {
				var filters = document.getElementById( cmspad.console.IDs.filters ).getElementsByTagName( 'SPAN' );
				var active = 0;
				for ( entry in cmspad.console.messageTypes ) {
					if ( cmspad.console.messageTypes[ entry ] ) active++;
				}
				var oneActiveFilter = ( active == 1 && cmspad.console.messageTypes[ type ] );
				for ( var i = 0; filters[ i ]; i++ ) {
					var spanType = filters[ i ].getAttributeNode( 'type' ).nodeValue;
					filters[ i ].className = ( oneActiveFilter || ( spanType == type ) ) ? spanType : spanType + 'Disabled';
					cmspad.console.messageTypes[ spanType ] = oneActiveFilter || ( spanType == type );
				}
			} else {
				cmspad.console.messageTypes[ type ] = ! cmspad.console.messageTypes[ type ];
				span.className = ( cmspad.console.messageTypes[ type ] ) ? type : type + 'Disabled';
			}
			//build outputList's class from messageTypes object
			var disabledTypes = [];
			for ( type in cmspad.console.messageTypes ) {
				if ( ! cmspad.console.messageTypes[ type ] ) disabledTypes.push( type );
			}
			disabledTypes.push( '' );
			cmspad.console.outputList.className = disabledTypes.join( 'Hidden ' );
			cmspad.console._scrollToBottom();
		}
	},
	_clickVis: function( evt ) {
		if ( !evt ) evt = window.event;
		var el = ( evt.target ) ? evt.target : evt.srcElement;
		cmspad.console.state.load = el.checked;
		cmspad.console._setState();
	},
	_scrollToBottom: function() { //scroll list output to the bottom
		this.outputList.scrollTop = this.outputList.scrollHeight;
	},
  _readKey: function( evt ) {
		if ( !evt ) evt = window.event;
		var code = 120; //F9 key
		if ( evt && evt.keyCode == code ) {
			var visible = cmspad.console.isVisible();
			if ( visible && evt.shiftKey && evt.altKey ) cmspad.console.clear();
			else if	 (visible && evt.shiftKey ) cmspad.console.move();
			else if	 (visible && evt.altKey ) cmspad.console.resize();
			else if ( !evt.shiftKey && !evt.altKey ) {
			  ( visible ) ? cmspad.console.hide() : cmspad.console.show();
			}
		}
	},
	_setState: function() {
		var props = [];
		for ( entry in this.state ) {
			var value = ( this.state[ entry ] && this.state[ entry ].constructor === String ) ? '"' + this.state[ entry ] + '"' : this.state[ entry ]; 
			props.push( entry + ':' + value );
		}
		props = props.join( ',' );
		cmspad.setCookie('cmspad_console', '{' + props + '}');
		var newClass = [];
		for ( word in this.classes ) {
			newClass.push( this.classes[ word ] );
		}
		this.cconsole.className = newClass.join( ' ' );
	},
  _getState: function() {
		var value = cmspad.getCookie('cmspad_console');
		return value ? eval( '(' + value + ')' ) : { pos:null, size:null, load:null };
	},
	_initialize: function(){
		this.state = this._getState();
		var body = document.getElementsByTagName( 'BODY' )[ 0 ];
		this.cconsole = body.appendChild( this._generateMarkup() );
		this.outputList = this.cconsole.getElementsByTagName( 'OL' )[ 0 ];
		this._backgroundImage();
		cmspad.addEvent( this.IDs.checkbox, 'click', this._clickVis );
		cmspad.addEvent( this.IDs.filters, 'click', this._clickFilter );
		cmspad.addEvent( this.IDs.controls, 'click', this._clickControl );
		cmspad.addEvent( document, 'keyup', this._readKey);
		this.resize( this.state.size );
		this.move( this.state.pos );
		if ( this.state.load) {
			this.show();
			document.getElementById( this.IDs.checkbox ).checked = true; 
		}
		this._scrollToBottom();
		cmspad.addEvent( window, 'unload', function() {
			cmspad.removeEvent( cmspad.console.IDs.checkbox, 'click', cmspad.console._clickVis );
			cmspad.removeEvent( cmspad.console.IDs.filters, 'click', cmspad.console._clickFilter );
			cmspad.removeEvent( cmspad.console.IDs.controls, 'click', cmspad.console._clickControl );
			cmspad.removeEvent( document, 'keyup', cmspad.console._readKey );
		});
	},
	initialize: function(){
		var cStyleSheet = cmspad.$('cmspad_console_stylesheet');
		if (cStyleSheet) {
			this._initialize();
		} else {
			window.status = cmspad.console.nls.LOADING;
			cStyleSheet = cmspad.includeStyle(cmspad.DOCUMENT_ROOT + 'kernel/res/cmspad.console.css', 'cmspad_console_stylesheet');
			if (window.attachEvent) {
				// IE 中，可以进行文件载入的监听
				cmspad.addEvent(cStyleSheet, 'load', function(){
					if(window.status == cmspad.console.nls.LOADING){
						window.status = '';
					}
					cmspad.console._initialize();
				});
			}else{
				// FF 中，只能监测样式表ID是否存在了
				var cssCount = 0;
				var cssCountListener = setInterval(function(){
					if(cmspad.$('cmspad_console_stylesheet')){
						if(window.status == cmspad.console.nls.LOADING){
							window.status = '';
						}
						cmspad.console._initialize();
						clearInterval(cssCountListener);
					}
				}, 100);
			}
		}
	}
});
window.onerror = function(msg,href,line){
	cmspad.console.error(msg + ': ' + line + '\n' + href);
};